(function ($) {
    var audio = function (t, options) {
        t = $(t);
        var a = this;
        a.player = t[0];
        a.defaultRate = 1;
        options = this.options = $.extend({
            autoplay: false,
            debug: false,
        }, options);

        if (t.hasClass('audio_ctl')) {
            t.attr("src", options.source);
        } else {
            t.addClass('audio_ctl');
            a.dom = $("<div class='audio " + (options.skin ? options.skin : '') + "' />").css({
                position: t.css('position'),
                left: t.css('left'),
                top: t.css('top'),
                width: t.css('width'),
                height: t.css('height'),
                margin: t.css('margin'),
                padding: t.css('padding')
            });
            var inner = $("<div class='audio_inner' />").appendTo(a.dom);
            var media = $("<div class='audio_media' />").appendTo(inner);
            if (a.player.tagName == 'AUDIO') {
                t.attr("preload", "auto")
                    .attr("src", options.source || '')
                    .attr("autobuffer", true)
                    .bind('loadstart', function () {
                        a.onLoadstart();
                    }).bind('progress', function (e) {
                    a.onProgress();
                }).bind('suspend', function (e) {
                    a.onSuspend();
                }).bind('abort', function (e) {
                    a.onAbort();
                }).bind('error', function (e) {
                    a.onError(e);
                }).bind('stalled', function (e) {
                    a.onStalled();
                }).bind('durationchange', function () {
                    a.onDurationchange();
                }).bind('loadedmetadata', function () {
                    a.onLoadedmetadata();
                }).bind('loadeddata', function () {
                    a.onLoadeddata();
                }).bind('canplay', function () {
                    a.onCanplay();
                }).bind('canplaythrough', function () {
                    a.onCanplaythrough();
                }).bind('waiting', function () {
                    a.onWaiting();
                }).bind('play', function () {
                    a.onPlay();
                }).bind('pause', function () {
                    a.onPause();
                }).bind('playing', function () {
                    a.onPlaying();
                }).bind('seeking', function () {
                    a.onSeeking();
                }).bind('seeked', function () {
                    a.onSeeked();
                }).bind('timeupdate', function () {
                    a.onTimeupdate();
                }).bind('ended', function () {
                    a.onEnded();
                }).bind('ratechange', function () {
                    a.onRatechange();
                }).bind('volumechange', function () {
                    a.onVolumechange();
                });
//				if (options.autoplay)
//					t.attr("autoplay", "autoplay");

                t.css({
                    display: 'none'
                });
            } else {
                alert('只能对AUDIO进行操作');
                return a;
            }

            a.controls = $('<div class="audio_controls" />').appendTo(inner);
            a.rail = $('<div class="audio_bar_rail" />').appendTo(a.controls);
            a.ctl_time_current = $('<div class="audio_time audio_current_container"><span class="audio_currentTime">00:00</span></div>').appendTo(a.rail);
            a.ctl_time = $("<div class='audio_time_rail'></div>").appendTo(a.rail);
            var time_slide = $("<a href='javascript:;' class='wp-time-total wp-time-slider'></a>").appendTo(a.ctl_time);
            bindKey(a, time_slide);
            time_slide.append('<span class="wp-time-buffering"></span>');
            time_slide.append('<span class="wp-time-loaded" style="width: 0%;"></span>');
            time_slide.append('<span class="wp-time-current" style="width: 0%;"></span>');
            time_slide.append('<span class="wp-time-handle"></span>');
            var time_tip = $('<span class="wp-time-float" style="display:none; left:30px;" />').appendTo(time_slide);
            var time_tip_current = $('<span class="wp-time-float-current"></span>').appendTo(time_tip);
            time_tip.append('<span class="wp-time-float-corner"></span>');
            a.ctl_time.hover(function (e) {
                time_tip.css('display','inline')
                if (a.player.duration)
                    time_tip.toggle();
            }).on('mousemove', function (e) {
                var left = e.pageX - a.ctl_time.offset().left;
                time_tip.css({'margin-left': (left - 48) + 'px'});
                if (a.player.duration == 'Infinity')
                    time_tip_current.text('不可用');
                else
                    time_tip_current.text(timeDispose(Math.floor(a.player.duration * (left / a.ctl_time.width()))));

            }).on('click', function (e) {
                if (a.player.duration == 'Infinity' || isNaN(a.player.duration))
                    return;

                var left = e.pageX - a.ctl_time.offset().left,
                    c = a.player.duration * (left / a.ctl_time.width());
                refreshTimeup(a, c);
                setTimeout(function () {
                    a.seek(c);
                }, 10);
                time_slide.focus();
            }).on('mouseleave', function (e) {
                time_tip.css('display','none')
            });
            a.ctl_time_duration = $("<div class='audio_time audio_current_container'><span class='audio_durationTime'>00:00</span></div>").appendTo(a.rail);

            a.operation = $("<div class='audio_bar_operation' />").appendTo(a.controls);
            a.rate(1);
            a.ctl_slow = $("<button type='button' class='audio_button audio_slow' title='快退'+options.quickProp+'秒'></button>")
                .appendTo(a.operation)
                .click(function (e) {
                    // 快退10秒
                    var val = a.player.currentTime;
                    if (val <= options.quickProp) {
                        a.player.currentTime = 0
                    } else {
                        a.player.currentTime += -options.quickProp
                    }
                    // if (a.player.playbackRate > 1) {
                    //     var value = Math.floor(a.player.playbackRate);
                    //     if (value !== a.player.playbackRate) {
                    //         a.player.playbackRate = value;
                    //     } else {
                    //         a.player.playbackRate--;
                    //     }
                    // } else {
                    //     var value = Math.floor(a.player.playbackRate * 10) / 10;
                    //     if (value !== a.player.playbackRate) {
                    //         a.player.playbackRate = value;
                    //     } else {
                    //         if (value > 0.5)
                    //             a.player.playbackRate = (a.player.playbackRate * 10 - 1) / 10;
                    //     }
                    // }
                });
            a.ctl_play = $("<button type='button' class='audio_button audio_play' title='播放'></button>")
                .appendTo(a.operation)
                .click(function (e) {
                    if (a.player.paused && t.attr('src'))
                        a.play();
                    else
                        a.pause();
                });
            a.ctl_quick = $("<button type='button' class='audio_button audio_quick' title='快进'+options.quickProp+'秒'></button>")
                .appendTo(a.operation)
                .click(function (e) {
                    var val = a.player.currentTime;
                    a.player.currentTime += options.quickProp;
                });
            a.ctl_speed = $("<select class='audio_speed'><option value='1'>默认</option><option value='0.5'>0.5倍速</option><option value='1'>1倍速</option>" +
                "<option value='1.25'>1.25倍速</option><option value='1.5'>1.5倍速</option><option value='2'>2倍速</option><option value='3'>3倍速</option></select>")
                .appendTo(a.operation)
                .change(function (e) {
                    console.log(e.target.value);
                    a.player.playbackRate = e.target.value;
                    a.defaultRate = e.target.value;
                    options.onRatechange && options.onRatechange(e.target.value);
                });
            bindKey(a, a.ctl_play);
            a.ctl_volume = $("<button type='button' class='audio_button audio_volume' title='静音'></button>")
                .appendTo(a.operation)
                .click(function (e) {
                    if (a.player.muted) {
                        a.mute(false);
                    } else {
                        a.mute(true);
                    }
                });
            var volumeSlide = $('<div class="audio_volume_slide" />').appendTo(a.operation);
            var defaultVolume = 60;
            if ($.cookie) {
                var d = $.cookie('audio_player_volume');
                if (d !== undefined && d !== null)
                    defaultVolume = parseInt(d);
            }
            a.volume(defaultVolume);
            volumeSlide.slider({
                range: "min",
                min: 0,
                max: 100,
                value: defaultVolume,
                slide: function (event, ui) {
                    if ($.cookie)
                        $.cookie('wisdge_player_volume', ui.value, {expires: 30});
                    a.volume(ui.value);
                    if (ui.value > 0)
                        a.mute(false);
                }
            });

            a.tip = $('<span />').text(t.attr('title') || '');
            $('<div class="tip" />').append(a.tip).appendTo(a.operation);

            inner.append("<div style='clear:both' />");
            t.before(a.dom);
            media.append(t);
        }

        return a;
    };

    audio.prototype = {
        onLoadstart: function () {
            var a = this;
            // 客户端开始请求数据
            a.loadCompleted = false;
            if (a.options.debug)
                console.log('loadstart');
            reset(a);
        },

        onProgress: function () {
            // 客户端正在请求数据
            if (this.options.debug)
                console.log('progress');
            if (!this.loadCompleted) {
                if (this.player.buffered.length > 0) {
                    var buffered = this.player.buffered.end(0);
                    var s = ((buffered / this.player.duration) * 100) + '%';
                    $(".wp-time-loaded", this.ctl_time).width(s);
                    if (buffered == this.player.duration)
                        this.loadCompleted = true;
                }
            }
        },

        onSuspend: function () {
            // 延迟下载
            if (this.options.debug)
                console.log('suspend');
        },

        onAbort: function () {
            // 客户端主动终止下载（不是因为错误引起）
            if (this.options.debug)
                console.log('abort');
        },

        onError: function (e) {
            // 请求数据时遇到错误
            if (this.options.debug)
                console.error('error: ', this.player.error);
        },

        onStalled: function () {
            // 网速失速
            if (this.options.debug)
                console.log('stalled');
        },

        onDurationchange: function () {
            // 资源长度改变
            if (this.options.debug)
                console.log('durationchange');
            getDuration(this);
        },

        onLoadedmetadata: function () {
            // 成功获取资源长度
            if (this.options.debug)
                console.log('loadedmetadata');
            //getDuration(this);
        },

        onLoadeddata: function () {
            // 成功获取资源
            if (this.options.debug)
                console.log('loadeddata');
            $("span.wp-time-buffering", this.ctl_time).hide();
        },

        onCanplay: function () {
            // 可以播放，但中途可能因为加载而暂停
            if (this.options.debug)
                console.log('canplay');
            if (this.options.autoplay && !this.played) {
                this.played = true;
                this.player.play();
            }
            this.canPlay = true;
            this.player.playbackRate = this.defaultRate;
        },

        onCanplaythrough: function () {
            // 可以播放，资源全部加载完毕
            if (this.options.debug)
                console.log('canplaythrough');
            this.loadCompleted = true;
            $(".wp-time-loaded", this.ctl_time).width('100%');
            //getDuration(this);
        },

        onPlay: function () {
            // 开始播放时触发
            var a = this;
            if (a.options.debug)
                console.log('play');
            playState(a, true);
            if (a.player.tagName == 'VIDEO')
                createHideTask(a);
            if ($.isFunction(a.options.onPlay))
                a.options.onPlay(a.player.src);
        },

        onPause: function () {
            // pause()触发
            var a = this;
            if (a.options.debug)
                console.log('pause');
            playState(a, false);
            if ($.isFunction(a.options.onPause))
                a.options.onPause(a.player.src);
        },

        onPlaying: function () {
            // 开始回放
            var a = this;
            if (a.options.debug)
                console.log('playing');
            if (a.layer_load)
                a.layer_load.hide();
            if ($.isFunction(a.options.onPlaying))
                a.options.onPlaying(a.player.src);
        },

        onWaiting: function () {
            // 等待数据，并非错误
            if (this.options.debug)
                console.log('waiting');
            if (this.layer_load)
                this.layer_load.show();
        },

        onSeeking: function () {
            // 寻找中
            if (this.options.debug)
                console.log('seeking')

            if (this.layer_load)
                this.layer_load.show();
        },

        onSeeked: function () {
            // 寻找完毕
            var a = this;
            a.player.playbackRate = a.defaultRate;
            if (a.options.debug)
                console.log('seeked');
            if (a.layer_load)
                a.layer_load.hide();
            if ($.isFunction(a.options.onSeeked))
                a.options.onSeeked({
                    time: a.player.currentTime,
                    display: timeDispose(Math.floor(a.player.currentTime))
                })
        },

        onTimeupdate: function () {
            // 播放时间改变
            var a = this;
            if (a.options.debug)
                console.log('timeupdate');
            refreshTimeup(a, a.player.currentTime);
            if ($.isFunction(a.options.onTimeupdate))
                a.options.onTimeupdate(a.player.currentTime);
            this.player.playbackRate =  this.defaultRate;
        },

        onEnded: function () {
            // 播放结束
            var a = this;
            if (a.options.debug)
                console.log('ended');
            a.restart();
            playState(a, false);
            if ($.isFunction(a.options.onEnded))
                a.options.onEnded(a.player.src);
        },

        onRatechange: function () {
            // 播放速率改变
            var a = this;
            if (a.options.debug)
                console.log('ratechange');
            if ($.isFunction(a.options.onRatechange))
                a.options.onRatechange(a.player.playbackRate);
            // this.defaultRate = this.player.playbackRate;
        },

        onVolumechange: function () {
            // 音量改变
            var a = this;
            if (a.options.debug)
                console.log('volumechange');
            if (a.player.muted)
                a.ctl_volume.addClass('mute');
            else
                a.ctl_volume.removeClass('mute');
            if ($.isFunction(a.options.onVolumechange))
                a.options.onVolumechange(a.player.volume);
        },

        play: function () {
            this.player.play();
        },

        pause: function () {
            this.player.pause();
        },

        restart: function () {
            if (this.player.canPlay)
                this.player.currentTime = 0;
        },

        volume: function (e) {
            this.player.volume = e / 100;
            if ($.cookie)
                $.cookie('audio_player_volume', e, {
                    expires: 30
                })
        },

        seek: function (current) {
            if (this.canPlay)
                this.player.currentTime = current;
        },

        mute: function (e) {
            this.player.muted = e;
            if (e) {
                $(".audio_volume_slide", this.dom).slider("value", 0);
                this.ctl_volume.addClass('mute').attr("title", "取消静音");
            } else {
                $(".audio_volume_slide", this.dom).slider("value", this.player.volume * 100);
                this.ctl_volume.removeClass('mute').attr("title", "静音");
            }
        },

        forward: function () {
            var step = 5, duration = this.player.duration, currentTime = this.player.currentTime;
            if (duration > 100)
                step = duration * 0.05;
            else if (duration < 20)
                step = 3;
            this.player.currentTime = currentTime > step ? currentTime - step : 0;
        },

        back: function () {
            var step = 5, duration = this.player.duration, currentTime = this.player.currentTime;
            if (duration > 100)
                step = duration * 0.05;
            else if (duration < 20)
                step = 3;
            this.player.currentTime = (currentTime + step < duration) ? currentTime + step : duration;
        },

        rate: function (e) {
            this.defaultRate = e;
        },

        source: function (e, type) {
            var a = this;
            if (e == undefined)
                return this.player.src;
            else {
                a.pause();
                a.restart();
                playState(a, false);
                reset(a);
                if (a.options.debug)
                    console.log('Audio source: ' + e);
                setTimeout(function () {
                    if (e == null || e == '') {
                        a.player.src = '';
                    } else
                        $(a.player).attr("src", e);
                    //a.player.src = e;
                }, 100)
            }
        },

    };

    var mediaplay = function (player) {
        this.player = player;
        this.duration = player.currentMedia.duratioin;
    };
    mediaplay.prototype = {
        play: function () {
            this.player.controls.play();
        }
    };

    var getDuration = function (fn) {
            if (fn.player.duration == 'Infinity' || isNaN(fn.player.duration))
                $('.audio_durationTime', fn.ctl_time_duration).text('--');
            else {
                var time = Math.round(fn.player.duration);
                $('.audio_durationTime', fn.ctl_time_duration).text(timeDispose(time));
            }
        },

        refreshTimeup = function (fn, currentTime) {
            var time = Math.round(currentTime);
            $('.audio_currentTime', fn.controls).text(timeDispose(time));

            var s = ((currentTime / fn.player.duration) * 100) + '%';
            $(".wp-time-current", fn.ctl_time).show().width(s);
            var x = ((currentTime / fn.player.duration) * fn.ctl_time.width() - 8) + 'px';
            $(".wp-time-handle", fn.ctl_time).show().css('left', x);
        },

        timeDispose = function (time) {
            var mins = Math.floor(time / 60);
            var secs = time - (mins * 60);
            return (mins < 10 ? ('0' + mins) : mins) + ":" + (secs < 10 ? ('0' + secs) : secs);
        },

        bindKey = function (fn, t) {
            t.on('keydown', function (e) {
                if (e.keyCode == 39)
                    fn.back();
                else if (e.keyCode == 37)
                    fn.forward();
            });
        },

        playState = function (fn, state) {
            if (state) {
                fn.ctl_play.removeClass('audio_play').removeClass('audio_stop').addClass('audio_pause');
                $("button", fn.ctl_play).attr('title', '暂停');
            } else {
                fn.ctl_play.removeClass('audio_pause').removeClass('audio_stop').addClass('audio_play');
                $("button", fn.ctl_play).attr('title', '播放');
            }
        },

        reset = function (fn) {
            $("span.wp-time-buffering", fn.ctl_time).show();
            $("span.wp-time-loaded", fn.ctl_time).width(0);
            $("span.wp-time-current", fn.ctl_time).hide();
            $("span.wp-time-handle", fn.ctl_time).hide();
            $('span.audio_currentTime', fn.controls).text('00:00');
            getDuration(fn)
            fn.played = false;
        };


    $.fn.audio = function (options) {
        var t = $(this);
        if (t.length != 1)
            alert("只能将audio方法用于唯一的HTML元素。");

        return t.data("audio") || new audio(t, options);
    }

})(jQuery);
